package s.k.gui.webtest.page;

import static org.junit.Assert.fail;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.openqa.selenium.WebElement;

import s.k.gui.webtest.Allocator;
import s.k.gui.webtest.BrowserWindow;
import s.k.gui.webtest.WebDriverBrowserWindow;
import s.k.gui.webtest.log.*;
import s.k.gui.webtest.constvalue.*;

import s.k.gui.webtest.basetools.SKBaseTools;
import s.k.gui.webtest.basetools.SKWindow;
import s.k.gui.webtest.element.Element;
import s.k.gui.webtest.element.locator.Locator;
import s.k.gui.webtest.element.locator.LocatorChain;
import s.k.gui.webtest.element.locator.LocatorValue;
import s.k.gui.webtest.element.tools.WebDriverElementExist;

public class SubPage implements LocatorValue {

	private s.k.gui.webtest.element.tools.WebElementExist exist;

	String fullName = "";

	private String comment;

	private String currentLocator;

	private LocatorChain infoChain = new LocatorChain();

	private WebElement element;

	private Locator locator;

	public void setComment(String comment) {

		this.comment = comment;

	}

	public String getComment() {

		return comment;
	}

	@Override
	public Locator getLocator() {

		return locator;
	}

	@Override
	public WebElement getElement() {
		// TODO Auto-generated method stub
		return element;
	}

	@Override
	public void setElement(WebElement element) {

		this.element = element;

	}

	@Override
	public String getLocatorCurrent() {

		return currentLocator;
	}

	@Override
	public void setLocatorCurrent(String currentLocator) {

		this.currentLocator = currentLocator;

	}

	@Override
	public boolean isExist() {

		currentLocator = "";

		return isSubPageExist(ConfigConstValue.defaultWaitCount);
	}

	@Override
	public LocatorChain getInfoChain() {

		return infoChain;
	}

	public void setFullName(String fullName) {

		this.fullName = fullName;

	}

	protected void init() {

		Field[] fields = this.getClass().getDeclaredFields();

		try {

			for (Field field : fields) {

				if (field.getModifiers() == ConstValue.nestedFatherObjectModifier) {

					continue;

				}
				Object o = field.get(this);

				if (o instanceof Element) {

					SKBaseTools.insertElementName((Element) o, field.getName());

					((Element) o).getInfoChain().addParentNode(
							this.getInfoChain().getInfoNodes());

					((Element) o).setFullName(fullName + field.getName());

					((Element) o).getInfoChain().addNode(this);

					elements.add((Element) o);

				} else if (o instanceof SubPage) {

					SKBaseTools.insertSubPageName((SubPage) o, field.getName());

					((SubPage) o).getInfoChain().addParentNode(
							this.getInfoChain().getInfoNodes());

					((SubPage) o).setFullName(fullName + field.getName());

					((SubPage) o).getInfoChain().addNode(this);

					((SubPage) o).init();

					this.subpages.add((SubPage) o);

				} else if (o instanceof Part) {

					SKBaseTools.insertPartName((Part) o, field.getName());

					((Part) o).getInfoChain().addParentNode(
							this.getInfoChain().getInfoNodes());

					((Part) o).setFullName(fullName + field.getName());

					((Part) o).getInfoChain().addNode(this);

					((Part) o).init();

					this.collections.add((Part) o);

				}
			}

		} catch (IllegalAccessException e) {

			e.printStackTrace();

		} catch (IllegalArgumentException e) {

			e.printStackTrace();
		}
	}

	protected List<Element> elements = new ArrayList<Element>();

	protected List<SubPage> subpages = new ArrayList<SubPage>();

	protected List<Part> collections = new ArrayList<Part>();

	
	protected MyLogger logger = MyLogger.getLogger(this.getClass().getName());

	public SubPage(String comment) {

		this.locator = new Locator();

		this.infoChain = new LocatorChain();

		this.comment = comment;
	}

	private boolean isSubPageExist(int waitCount) {

		BrowserWindow currentWindow = Allocator.getInstance().currentWindow;

		if (currentWindow instanceof WebDriverBrowserWindow) {

			exist = new WebDriverElementExist(this);

		}

		return exist.isElementExist(waitCount);
	}


	public void assertExist() {

		StringBuilder message = new StringBuilder();

		if (isExist()) {

			message.append(this.comment + ":");

			message.append("");

			logger.info(message);

		} else {

			message.append(this.comment + ":");

			message.append("");

			logger.error(message);

			SKWindow.closeAllWindows();

			fail(message.toString());

		}
	}

	public void assertNotExist() {

		StringBuilder message = new StringBuilder();

		if (!isExist()) {

			message.append(this.comment + ":");

			message.append("");

			logger.info(message);

		} else {

			message.append(this.comment + ":");

			message.append("");

			logger.error(message);

			SKWindow.closeAllWindows();

			fail(message.toString());

		}
	}

	public void verifyExist() {

		StringBuilder message = new StringBuilder();

		if (isExist()) {

			message.append(this.comment + ":");

			message.append("");

			logger.info(message);

		} else {

			message.append(this.comment + ":");

			message.append("");

			logger.error(message);

		}
	}



	public void verifyNotExist() {

		StringBuilder message = new StringBuilder();

		if (!isExist()) {

			message.append(this.comment + ":");

			message.append("");

			logger.info(message);

		} else {

			message.append(this.comment + ":");

			message.append("");

			logger.error(message);
		}
	}

	
	public boolean waitForExist() {

		if (!isSubPageExist(ConfigConstValue.waitCount)) {

			logger.error("");

			return false;

		}
		return true;

	}


	public void waitForDisppear() {

		int waitCount = 0;

		while (waitCount++ < ConfigConstValue.waitCount) {

			if (!exist.isElementExistForCheckOnce())

				return;
		}
	}

	protected void getMuliLevelLocatorInfo() {

		if (locator.getLocatorById() != null
				&& !"".equalsIgnoreCase(locator.getLocatorById()))

			currentLocator = locator.getXpathFromId();

		else {

			for (int i = 1; i < infoChain.getInfoNodes().size(); i++) {

				if (infoChain.getInfoNodes().get(i).getLocator()
						.getLocatorById() != null
						&& !"".equalsIgnoreCase(infoChain.getInfoNodes().get(i)
								.getLocator().getLocatorById())) {

					currentLocator = infoChain.getInfoNodes().get(i)
							.getLocator().getXpathFromId();

				} else {

					if (infoChain.getInfoNodes().get(i) instanceof Frame) {

						currentLocator = "";

					} else {

						currentLocator += infoChain.getInfoNodes().get(i)
								.getLocator().getLocatorByXpath();

						if (infoChain.getInfoNodes().get(i) instanceof Part) {

							currentLocator += "["
									+ ((Part) infoChain.getInfoNodes().get(i))
											.getIndex() + "]";
						}
					}
				}

			}
			currentLocator += locator.getLocatorByXpath();
		}
	}

	public void addIDLocator(String id) {

		this.locator.addIdLocator(id);

	}

	public void addNameLocator(String name) {

		this.locator.addNameLocator(name);

	}

	public void addXpathLocator(String xpath) {

		this.locator.addXpathLocator(xpath);

	}

	public void addCSSLocator(String css) {

		this.locator.addCSSLocator(css);

	}

	public void addLinkTextLocator(String linkText) {

		this.locator.addLinkTextLocator(linkText);

	}

	public void addPartialLinkTextLocator(String partialLinkText) {

		this.locator.addPartialLinkTextLocator(partialLinkText);

	}

	public void addAttributeLocator(String attributeName, String attributeValue) {

		this.locator.addAttributeLocator(attributeName, attributeValue);
	}
	
	public void addClassLocator(String className){
		
		this.locator.addClassLocator(className);
	}
}
